#include "ui_number.h"
#include "ui_widget.h"
#include "graphics/image.h"
#include "graphics/graphics.h"

#include "script/scripthelper.h"

#include "util/log.h"				// log
#include "util/common_macros.h"		// macros
#include "util/mmgr.h"		    

#include <cassert>
using namespace script;
using namespace ui;
using namespace LuaPlus;

const float				CommaSize = 0.3f;


UINumber::UINumber() :
	m_pImage(NULL),
	m_IsTime(false)
{

}

UINumber::~UINumber()
{
	UTIL_SAFE_DELETE(m_pImage);

}

void UINumber::Load(const std::string& File)
{
	LuaPlus::LuaState*	pScript = ScriptHelper::CreateLuaState();
	if (!ScriptHelper::DoFile(*pScript, File))
	{
		_LOG(MSG_ERROR, "Unable to load UINumber ini file" << File << "!");
		 LuaState::Destroy( pScript );
		return ;
	} else
	{
		LuaPlus::LuaObject	NumberInfo = ScriptHelper::GetObj(*pScript, "Number");
		if (NumberInfo.IsTable())
		{
			std::string		Image = ScriptHelper::GetTableString(NumberInfo, "Image");
			math::Vec2		Size = ScriptHelper::GetTableVec2(NumberInfo, "Size", math::Vec2(0.02f, 0.03f));
			LuaPlus::LuaObject	Coords = NumberInfo.GetByName("Coords");
			float	TexCoordA[UINumber::DIGIT_COUNT] = 
			{
				0.0f,				// 0
				64.0f/700.0f,		// 1
				111.0f/700.0f,		// 2
				178.0f/700.0f,		// 3
				236.0f/700.0f,		// 4
				297.0f/700.0f,		// 5
				357.0f/700.0f,		// 6
				412.0f/700.0f,		// 7
				475.0f/700.0f,		// 8
				530.0f/700.0f,		// 9
				592.0f/700.0f,		// ,
				618.0f/700.0f,		// :
				618.0f/700.0f,		// end
			};
			if (Coords.IsTable())
			{
				int Count = UTIL_LOW(UINumber::DIGIT_COUNT, Coords.GetTableCount());
				for (int i=0; i<Count; i++)
				{
					int AbsCount = Coords.GetTableCount();
//					if ( < i && Coords.GetByIndex(i+1).IsFIsNumber())
					{
						TexCoordA[i] = Coords.GetByIndex(i+1).GetFloat();
					}
				}
			} 
			Init(Image, TexCoordA, Size);
		}
	}
	LuaState::Destroy( pScript );
}

void UINumber::Init(const	std::string& File, float	CoordA[], const math::Vec2& Size)
{
	m_pImage = GetGraphics()->LoadImageFromFile(File);
	memcpy(m_CoordA, CoordA, sizeof(m_CoordA));
	m_Size = Size;
}

void	UINumber::SetImage()
{
	if (m_pImage)
			m_pImage->SetTextureStage(0);
}

int		UINumber::FillScaledBuffer(int num, const math::Vec2& ScreenPos, bool Comma,  Graphics::Vertex2D* VertA, int		MaxVert, COLOR baseColor, const math::Vec2& BaseSize)
{
	//if (num < 0) return 0;

	unsigned char DigitA[MAX_DIGIT];
	int	DigitC = 0;
	
	float			ScreenWidth = (float)GetGraphics()->GetScreenWidth();
	float			ScreenHeight = (float)GetGraphics()->GetScreenHeight();


	math::Vec2	Pos(ScreenPos.x * ScreenWidth, ScreenPos.y * ScreenHeight);
	math::Vec2	Size(BaseSize.x * ScreenWidth, BaseSize.y * ScreenHeight);
	
	if (!m_IsTime)
	{
		int	CommaCount = 0;
		int absnum = abs(num);

		while (absnum > 9)
		{
			DigitA[DigitC++] = absnum % 10;
			absnum = absnum / 10;
			CommaCount++;
			if (CommaCount >= 3)
			{
				CommaCount = 0;
				if (Comma)
					DigitA[DigitC++] = DIGIT_COMMA;
			}
		}
		DigitA[DigitC++] = absnum;

		if (num<0)
			DigitA[DigitC++] = DIGIT_MINUS;

	} else
	{
		int Sec = num % 60;
		int	Min = num / 60;
		DigitA[DigitC++] = Sec % 10;
		DigitA[DigitC++] = Sec / 10;
		if (Min > 0) 
		{
			DigitA[DigitC++] = DIGIT_COLON;
			DigitA[DigitC++] = Min % 10;
			if (Min >= 10)	DigitA[DigitC++] = Min / 10;
		} 
	}

	unsigned int				VertI = 0;
	math::Vec2					From = Pos;
	float						Depth = 0.0f;
	for (int i=0; i<DigitC; i++)
	{
		int	Digit = DigitA[DigitC-i-1];
		float	tx1 = m_CoordA[Digit];
		float	tx2 = m_CoordA[Digit+1];
		float	ty1 = 0.0f;
		float	ty2 = 1.0f;
		unsigned int _Color = baseColor; 
		math::Vec2 To = From + Size;

		if (Digit >= DIGIT_COMMA && Digit != DIGIT_MINUS)
			To.x = From.x + (CommaSize * Size.x);

		VertA[VertI++].Fill(From.x,To.y,				_Color,	 tx1, ty2 );
		VertA[VertI++].Fill(From.x,From.y,				_Color,  tx1, ty1 );
		VertA[VertI++].Fill(To.x,To.y,					_Color,	 tx2, ty2 );
		VertA[VertI++].Fill(To.x,From.y,				_Color,	 tx2, ty1 );
		VertA[VertI++].Fill(To.x,To.y,					_Color,	 tx2, ty2 );
		VertA[VertI++].Fill(From.x,From.y,				_Color,  tx1, ty1 );
		
		if (Digit >= DIGIT_COMMA && Digit != DIGIT_MINUS)
			From = From + math::Vec2(Size.x*CommaSize, 0);
		else
			From = From + math::Vec2(Size.x, 0);
	}
	return VertI;
}

int		UINumber::FillBuffer(int num, const math::Vec2& ScreenPos, bool Comma,  Graphics::Vertex2D* VertA, int		MaxVert, COLOR baseColor)
{
	return FillScaledBuffer(num, ScreenPos, Comma,  VertA, MaxVert, baseColor, m_Size);
}

void UINumber::Draw(int	num, const math::Vec2& ScreenPos, bool Comma, COLOR Col )
{
	DrawScaled(num, ScreenPos, 1, Comma, Col);
}
void UINumber::Draw(int	Number, UIWidget* Box, int Align, bool Comma, COLOR Col)
{
	DrawScaled(Number, Box, 1, Align, Comma, Col);
}

void UINumber::DrawScaled(int	Number, const math::Vec2& Pos, float Scale, bool Comma , COLOR Col )
{
	Graphics::Vertex2D			VertA[MAX_DIGIT*6];
	unsigned int				VertI=0;

	SetImage();
	VertI = FillScaledBuffer(Number, Pos, Comma, VertA, MAX_DIGIT*6, Col, m_Size * Scale);
	GetGraphics()->DrawVertex2D(VertA, VertI);
}



void	UINumber::DrawScaled(int	Number, UIWidget* Box, float Scale, int Align, bool Comma, COLOR Col)
{
	if (!Box) return;
	if (Align == 0)
	{
		DrawScaled(Number, Box->GetPosition(), Scale, Comma, Col);
	} else if (Align == 1)
	{
		math::Vec2		ScreenSize;
		math::Vec2		ScreenPos;
		math::Vec2		Pos = Box->GetPosition() ;
		math::Vec2		Size = Box->GetSize();
		GetScreenSize(Number, ScreenSize, Comma);
		ScreenSize = ScreenSize*Scale;
		ScreenPos.x = Pos.x + ((Size.x - ScreenSize.x)*0.5f) ;
		ScreenPos.y = Pos.y + ((Size.y - ScreenSize.y) * 0.5f);

		DrawScaled((int)Number, ScreenPos, Scale, Comma, Col);
	
	} else	if (Align == 2)
	{
		math::Vec2		ScreenSize;
		math::Vec2		ScreenPos;
		math::Vec2		Pos = Box->GetPosition() ;
		math::Vec2		Size = Box->GetSize();
		GetScreenSize(Number, ScreenSize, Comma);
		ScreenSize = ScreenSize*Scale;
		ScreenPos.x = Pos.x + Size.x - ScreenSize.x ;
		ScreenPos.y = Pos.y + ((Size.y - ScreenSize.y) * 0.5f);

		DrawScaled((int)Number, ScreenPos, Scale, Comma, Col);
	}
}


int	UINumber::GetDigitC(int num, bool Comma)
{
	int	CommaCount = 0;
	int DigitC = 0;
	if (!m_IsTime)
	{
		int absnum = abs(num);
		while (absnum > 9)
		{
			DigitC++;
			absnum = absnum / 10;
			CommaCount++;
			if (CommaCount >= 3 && Comma)
			{
				CommaCount = 0;
				DigitC++;
			}
		}
		DigitC++;
		if (num<0)
			DigitC++;
	} else
	{
		int Sec = num % 60;
		int	Min = num / 60;
		if (Min > 0) 
		{
			if (Min >= 10)	DigitC++;
			DigitC++;		// min LSD
			DigitC++;		// colon
		} 
		DigitC++;			// sec MSB
		DigitC++;			// sec LSB
	}
	return DigitC;
}

void	UINumber::GetScreenSize(int num, math::Vec2& Size, bool Comma)
{
	Size.x = m_Size.x;
	Size.y = m_Size.y;
	int	CommaCount = 0;
	if (!m_IsTime)
	{
		int absnum = abs(num);
		while (absnum > 9)
		{
			Size.x += m_Size.x;
			
			absnum = absnum / 10;
			CommaCount++;
			if (CommaCount >= 3 && Comma)
			{
				Size.x += m_Size.x*CommaSize;
				CommaCount = 0;
			}
		}

		if (num<0)
			Size.x += m_Size.x;

	} else
	{
		int Sec = num % 60;
		int	Min = num / 60;
		if (Min > 0) 
		{
			if (Min >= 10)	Size.x += m_Size.x;
			Size.x += m_Size.x;
			Size.x += m_Size.x *CommaSize;
		} 
		Size.x += m_Size.x;
		Size.x += m_Size.x;
	}
}
